#pragma once

#include "zen_vap_object.h"

#include "zen_vap_helper.h"
#include "zen_matrix.h"
#include "zen_app.h"

namespace Zen { namespace Vap {

	class TouchDispatcher;

	class TouchHandle : public Object
	{
	public:
		virtual bool onTouchDown(AppTouch touch) { return true; }

		virtual bool onTouchMove(AppTouch touch) { return true; }

		virtual bool onTouchUp(AppTouch touch) { return true; }

		virtual bool onTouchCancel(AppTouch touch) { return true; }

		void setEnabled(bool v);

		bool isEnabled() { return m_is_enabled; }

		bool isActived() { return isEnabled() && m_dispatcher != nullptr; }

		void setPriority(int v);

		int getPriority() { return m_priority; }

		void remove();

		TouchDispatcher * getDispatcher() { return m_dispatcher; }
	protected:
		bool m_is_enabled = true;
		int m_priority = 0;
		TouchDispatcher * m_dispatcher = nullptr;

		friend class TouchDispatcher;
	};
	/*!
	 @class
	 @abstract touch information. `AppTouch` and attached node.
	 */
	struct TouchInfo {
		AppTouch touch;
		std::weak_ptr<TouchHandle> attached_handle;
	};

	class TouchDispatcher
	{
	public:
		void bindTouchHandle(std::shared_ptr<TouchHandle> handle);

		void removeTouchHandle(std::shared_ptr<TouchHandle> handle);

		void removeAllTouchHandles();

		std::map<uint32_t, TouchInfo> const & getTouches();

		void onTouchDown(AppTouch touch);

		void onTouchMove(AppTouch touch);

		void onTouchUp(AppTouch touch);

		void onTouchCancel(AppTouch touch);

		void clearPriorityDirty();

		void setPriorityDirty();
	protected:
		std::map<uint32_t/*AppTouch::no*/, TouchInfo > m_touches;
		std::vector<std::shared_ptr<TouchHandle> > m_touch_handles;
		std::shared_ptr<TouchHandle> m_current_touch_handle = nullptr;
		bool m_is_handles_priority_dirty = false;

	};
}}
